<?php
declare (strict_types=1);

namespace app\common\queue\learn;

use app\common\library\Queue;
use app\course\logic\base\{CourseSection, CourseStudent};
use app\course\model\payment\{PaymentOrderItem as POI};
use app\course\model\record\{LearnCourseRecord, LearnDailyRecord};
use app\course\model\video\CourseSectionVideo;
use think\facade\{Db, Request};

class Record
{
    // 完成条件
    private $cpcd;
    // 课时dataID
    private $cdid;
    // 课程类型
    private $courseType;

    public function run()
    {
        $param      = Request::post();
        $course_id  = $param['course_id'] ?? 0;
        $section_id = $param['section_id'] ?? 0;
        $mid        = $param['mid'] ?? 0;

        if (!$mid || !$course_id || !$section_id) return;
        // 检查课时购买
        if (!$this->checkSecBuy($mid, $course_id, $section_id)) return;
        // 课程与课时关系
        if (!$this->getSectionData($course_id, $section_id)) return;
        //
        switch ($this->courseType) {
            case 1: // 点播
                $this->handleVideoRecord($param);
                break;
            case 2: // 直播
                $this->handleLiveRecord($param);
                break;
        }
        // 课程完成度队列
        Queue::push('LearnRate', ['mid' => $mid, 'course_id' => $course_id], 15);
    }

    // 获取课时信息
    public function getSectionData($course_id, $section_id): bool
    {
        $section = app(CourseSection::class)->field('course_type,course_data_id,completion_conditions')->where('course_id', $course_id)->where('id', $section_id)->where('is_last', 1)->findOrEmpty();

        if ($section->isEmpty()) return false;
        $this->cpcd       = $section->completion_conditions;
        $this->cdid       = $section->course_data_id;
        $this->courseType = $section->course_type;
        return true;
    }

    public function handleVideoRecord($data)
    {
        // 参数
        $course_id    = $data['course_id'];
        $section_id   = $data['section_id'];
        $mid          = $data['mid'];
        $date_time    = $data['time'];  // time();
        $current_time = $data['current_time'] ?? 0;  // time();

        // 课件信息获取
        $sectionData     = app(CourseSectionVideo::class)->with(['attach'])->where('id', $this->cdid)->findOrEmpty()->append(['data_type_text']);
        $duration        = $sectionData->getAttr('duration');
        $secDataType     = $sectionData->data_type;
        $completion_time = $this->cpcd * 60;
        // $isAV            = in_array($secDataType, [1, 2]);
        // $current_time    = $isAV ? $current_time : ($current_time % 10 ?: 10);
        $finished        = 1;

        /* 学习记录操作 start */
        Db::startTrans();
        // 加锁，防止多线程拥堵造成 后推送数据 先执行
        $record = app(LearnCourseRecord::class)->existRecord($course_id, $section_id, $mid)->lock(true)->findOrEmpty();
        if ($record->isEmpty()) {
            $total_time = min(10, $current_time);
            // 添加数据
            $course_record = LearnCourseRecord::create([
                'course_id'         => $course_id,
                'section_id'        => $section_id,
                'section_data_type' => $secDataType,
                'user_id'           => $mid,
                // 'current_time'      => $isAV ? $current_time : 0,
                'current_time'      => $current_time,
                'total_time'        => $total_time,
                'course_type'       => 1,
                'section_duration'  => $duration ?: 0,
                'completion_time'   => $completion_time,
                'finished'          => intval($completion_time <= $total_time)
                // 'finished'          => $isAV ? intval($completion_time <= $total_time) : $finished
            ]);

            // 当前用户学习累积记录
            $daily_record = $this->updateDailyRecord($mid, $total_time);

            // 回滚
            $rollback = $course_record->isEmpty() || !$daily_record;

        } else if ($date_time > $record->update_time) {
            // 计算时间
            $time     = $date_time - $record->update_time;                // 请求时间与上次更新时间差
            $time     = min($time, 10);                             // 请求时间超出10秒按10秒计算
            $_time    = $current_time - $record->current_time;            // 当前进度与上次记录进度
            $_time    = $_time < 0 ? 0 : ($_time > 10 ? $time : $_time);  // 进度差时间小于0为重看记0，大于10为拖动记$time
            $add_time = min($_time, $time);
            // 修改数据
            $record->section_data_type = $secDataType;
            $record->total_time        = $record->total_time + $add_time;
            // 完成状态
            // $finished = $isAV ? intval($completion_time <= $record->total_time) : $finished;
            $finished = intval($completion_time <= $record->total_time);
            $finished = $record->finished ?: $finished;
            //
            // $record->current_time     = $isAV ? $current_time : 0;
            $record->current_time     = $current_time;
            $record->section_duration = $duration ?: 0;
            $record->completion_time  = $completion_time;
            $record->finished         = $finished;
            $record->update_time      = $date_time;
            // 保存数据
            $course_record = $record->save();
            // 当前用户学习累积记录
            $daily_record = $this->updateDailyRecord($mid, $add_time);
            // 回滚
            $rollback = !$course_record || !$daily_record;

        } else {
            $rollback = false;
        }

        if ($rollback) {
            Db::rollback();
        } else {
            Db::commit();
        }
    }

    public function handleLiveRecord($data)
    {
        $course_id  = $data['course_id'];
        $section_id = $data['section_id'];
        $mid        = $data['mid'];
        // 需要观看多长时间才算完成
        $completion_time = $this->cpcd * 60;
        // 当前观看时长:单位秒
        $watchTime = $data['watch_time'] ?? 0;

        /* 学习记录操作 start */
        Db::startTrans();
        // 加锁，防止多线程拥堵造成 后推送数据 先执行
        $record = app(LearnCourseRecord::class)->existRecord($course_id, $section_id, $mid)->lock(true)->findOrEmpty();

        if ($record->isEmpty()) {
            // 添加数据
            $course_record = LearnCourseRecord::create([
                'course_id'       => $course_id,
                'section_id'      => $section_id,
                'user_id'         => $mid,
                'course_type'     => 2,
                'completion_time' => $completion_time,
                'total_time'      => $watchTime,
                'finished'        => intval($completion_time <= $watchTime),
            ]);
            // 当前用户学习累积记录
            $daily_record = $this->updateDailyRecord($mid, $watchTime);

            $rollback = $course_record->isEmpty() || !$daily_record;

        } else {
            $record->completion_time = $completion_time;
            $record->total_time      = $record->total_time + $watchTime;
            $record->finished        = $record->finished ? 1 : intval($completion_time <= $record->total_time);
            // 保存数据
            $course_record = $record->save();
            // 当前用户学习累积记录
            $daily_record = $this->updateDailyRecord($mid, $watchTime);
            // 回滚
            $rollback = !$course_record || !$daily_record;
        }

        if ($rollback) {
            Db::rollback();
        } else {
            Db::commit();
        }
    }

    // 更新每日学习记录数据
    public function updateDailyRecord($mid, $add_time): int
    {
        $daily      = app(LearnDailyRecord::class)->existRecord($mid)->findOrEmpty();
        $today_date = strtotime(date('Y-m-d'));

        if ($daily->isEmpty()) {
            $daily = LearnDailyRecord::create([
                'user_id'          => $mid,
                'days'             => 1,
                'today_learn_time' => $add_time,
                'total_learn_time' => $add_time,
                'week_learn_time'  => $add_time,
            ]);
            return $daily->isEmpty() ? 0 : 1;
        } else {
            if ($today_date < $daily->update_time) {
                // 上次更新为今天
                $daily->today_learn_time += $add_time;
                $daily->total_learn_time += $add_time;
            } else if ($today_date - 86400 > $daily->update_time) {
                // 上次更新为昨天之前
                $daily->today_learn_time = $add_time;
                $daily->total_learn_time += 10;
                $daily->days             = 1;
            } else {
                // 上次更新为昨天
                $daily->today_learn_time = $add_time;
                $daily->total_learn_time += 10;
                $daily->days             += 1;
            }
            // 本周学习时长处理
            $startWeek = strtotime(date('Y-m-d', (time() - ((date('w') == 0 ? 7 : date('w')) - 1) * 24 * 3600)));// 周一
            $endWeek   = ($startWeek+86400*7)-1;// 周日
            if ($startWeek > $daily->update_time) {
                // 上次更新为上周之前
                $daily->week_learn_time = $add_time;
            } else if ($startWeek < $daily->update_time && $daily->update_time < $endWeek) {
                // 上次更新为本周内
                $daily->week_learn_time += $add_time;
            }
            // 保存
            return intval($daily->save());
        }
    }

    private function checkSecBuy($user_id, $course_id, $section_id): bool
    {
        // 判断课程是否购买
        $has = app(CourseStudent::class)->where('user_id', $user_id)->where('course_id', $course_id)->findOrEmpty();
        if ($has->isEmpty()) {
            // 判断课程是否属于班级课
            if (app(CourseStudent::class)->courseBelongsClasses($course_id)) {
                // 判断用户是否购买班级课
                if (!app(CourseStudent::class)->courseBelongsUserClasses($course_id, $user_id)) return false;
            } else {
                $has = app(POI::class)->whereUserId($user_id)->whereProductId($course_id)->whereSectionId($section_id)->findOrEmpty();
                if ($has->isEmpty()) return false;
            }
        }
        return true;
    }
}
